import logging
from dataclasses import dataclass
import pytest
from bs4 import BeautifulSoup
from config import datas
from common.request_util_test import RequestUtil
from common.test_yaml_util_test import YamlUtil


@dataclass
class LoginParams:
    url: str
    gorilla_csrf_token: str
    get_then: str
    password: str


class TestLogin:
    @classmethod
    def _get_gorilla_csrf_token_and_get_then(cls, url: str):
        '''
        获取gorilla_csrf_token和get_then
        '''
        info = []
        req = RequestUtil().send_request('get', url)
        soup = BeautifulSoup(req.text, 'html.parser')
        all_input_label = soup.find_all('input')
        for i in all_input_label:
            if i['name'] == 'gorilla.csrf.Token':
                gorilla_csrf_token = i['value']
                info.append(gorilla_csrf_token)
            if i['name'] == 'then':
                get_then = i['value']
                info.append(get_then)
        return info

    @classmethod
    def _send_account_info(cls, params: LoginParams, data: dict):
        '''
        该函数用于登发送录时账号和密码或发送初次登录时修改密码
        '''
        header = {"Content-Type": "application/json", "X-Csrf-Token": params.gorilla_csrf_token}
        req = RequestUtil().send_request('post', params.url, headers=header, json=data)
        return req

    # @pytest.mark.normal
    # @pytest.mark.abnormal
    @pytest.mark.always_run
    @pytest.mark.parametrize('logininfo', YamlUtil().read_testcase_yaml('v24.06/login/1_login.yaml'))
    @classmethod
    def test_get_login(cls, logininfo, get_cookie):
        # 1.触发管理面的登录功能
        base_url = datas.baseUrl
        url = base_url + logininfo['request']['url']
        method = logininfo['request']['method']
        req = RequestUtil().send_request(method, url)
        location_code = req.headers['Location']
        # 2.生成用户授权码接口
        url_code = base_url + location_code
        req_code = RequestUtil().send_request('get', url_code)
        location_page = req_code.headers['Location']
        # 3.获取用户登录界面接口
        url_page = base_url + location_page
        gorilla_csrf_token = cls._get_gorilla_csrf_token_and_get_then(url_page)[0]
        get_then = cls._get_gorilla_csrf_token_and_get_then(url_page)[1]
        # 4.发送用户账号密码接口
        url_info = '/oauth2/auth/login/fuyaoPasswordProvider'
        url_send_info = base_url + url_info
        params = LoginParams(url_send_info, gorilla_csrf_token, get_then, datas.PASSWORD)
        password = [int(i) for i in params.password[1:-1].split(',')]
        data = {"username": datas.USERNAME, "password": password, "then": get_then}
        req_send_info = cls._send_account_info(params, data)
        location_code_again = req_send_info.headers['Location']
        # 5.生成用户授权码接口
        url_code_again = base_url + location_code_again
        req_code_again = RequestUtil().send_request('get', url_code_again)  # 输入账号和密码后调此接口来判断账号密码是否正确，及是否首次登录
        # location_callback = req_code_again.headers['Location']
        url_pw_confirm = '/oauth2/auth/password/confirm/fuyaoPasswordProvider'
        if 'Location' not in req_code_again.headers:
            logging.info('检测到为非首次登录，使用NEWPASSWORD进行登录')
            params = LoginParams(url_send_info, gorilla_csrf_token, get_then, datas.NEWPASSWORD)
            password = [int(i) for i in params.password[1:-1].split(',')]
            data = {"username": datas.USERNAME, "password": password, "then": get_then}
            req_send_info = cls._send_account_info(params, data)
            location_code_again = req_send_info.headers['Location']
        else:
            location_callback = req_code_again.headers['Location']
            logging.info('检测到为首次登录，跳转至首次登录修改密码')
            # 跳转到初次修改密码
            url_get_pw_confirm = base_url + location_callback
            # 获取初次修改密码界面接口
            gorilla_csrf_token_pw_confirm = cls._get_gorilla_csrf_token_and_get_then(url_get_pw_confirm)[0]
            get_then_pw_confirm = cls._get_gorilla_csrf_token_and_get_then(url_get_pw_confirm)[1]
            # 发送新密码和确认密码
            url_get_pw_confirm = base_url + url_pw_confirm
            params = LoginParams(url_get_pw_confirm, gorilla_csrf_token_pw_confirm, get_then_pw_confirm,
                                 datas.NEWPASSWORD)
            password = [int(i) for i in params.password[1:-1].split(',')]
            data = {"new_password": password, "then": get_then}
            req_send_info_pw_confirm = cls._send_account_info(params, data)
            location_code_again = req_send_info_pw_confirm.headers['Location']
            # url_callback = base_url + location_callback
        # 5.生成用户授权码接口
        url_code_again = base_url + location_code_again
        req_code = RequestUtil().send_request('get', url_code_again)
        location_callback = req_code.headers['Location']
        # 6.授权code回调接口
        url_callback = base_url + location_callback
        req_callback = RequestUtil().send_request('get', url_callback)
        location_check = req_callback.headers['Location']
        # 7.检查登录成功
        url_successful = base_url + location_check
        req_successful = RequestUtil().send_request('get', url_successful)
        get_cookie['value'] = req_successful.request.headers["Cookie"]
        assert req_successful.status_code == 200
        logging.info('登录成功')


if __name__ == '__main__':
    pytest.main(["-s", "test_1login.py"])
